package org.proteored.miapeapi.xml.gi;

import java.io.File;
import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.proteored.miapeapi.cv.ControlVocabularyManager;
import org.proteored.miapeapi.exceptions.IllegalMiapeArgumentException;
import org.proteored.miapeapi.exceptions.MiapeDatabaseException;
import org.proteored.miapeapi.exceptions.MiapeSecurityException;
import org.proteored.miapeapi.interfaces.gi.MiapeGIDocument;
import org.proteored.miapeapi.interfaces.persistence.PersistenceManager;
import org.proteored.miapeapi.interfaces.xml.MiapeXmlFile;
import org.proteored.miapeapi.interfaces.xml.XmlMiapeFactory;
import org.proteored.miapeapi.xml.gi.adapter.MiapeGiXMLAdapter;
import org.proteored.miapeapi.xml.gi.autogenerated.GIMIAPEGI;

/**
 * Class that provides the methods to convert a MIAPE GI XML to the MIAPE GI
 * model and vice versa.
 * 
 * @author Salvador
 * 
 */
public class MiapeGIXmlFactory implements XmlMiapeFactory<MiapeGIDocument> {
	private static MiapeGIXmlFactory instance;
	private JAXBContext jc;

	private MiapeGIXmlFactory() {
		try {
			jc = JAXBContext.newInstance("org.proteored.miapeapi.xml.gi.autogenerated");
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	public static MiapeGIXmlFactory getFactory() {
		if (instance == null) {
			instance = new MiapeGIXmlFactory();
		}
		return instance;
	}

	@Override
	public MiapeGIDocument toDocument(MiapeXmlFile<MiapeGIDocument> xmlFile,
			ControlVocabularyManager cvManager, PersistenceManager db, String user, String password)
			throws MiapeDatabaseException, MiapeSecurityException, IllegalMiapeArgumentException {
		if (cvManager == null)
			throw new IllegalMiapeArgumentException("ControlVocabularyManager is not set");
		return getFactory().create(xmlFile, db, cvManager, user, password);
	}

	private MiapeGIDocument create(MiapeXmlFile<MiapeGIDocument> xmlFile,
			PersistenceManager databaseManager, ControlVocabularyManager cvManager,
			String userName, String password) {
		MiapeGIDocument result = null;
		try {

			GIMIAPEGI miapeGI = (GIMIAPEGI) jc.createUnmarshaller().unmarshal(xmlFile.toFile());
			if (databaseManager == null) {
				result = new MiapeGIDocumentImpl(miapeGI, null, cvManager, userName, password);
			} else {
				result = new MiapeGIDocumentImpl(miapeGI, cvManager, databaseManager, userName,
						password);
			}
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	private MiapeXmlFile<MiapeGIDocument> create(MiapeGIDocument document,
			ControlVocabularyManager controlVocabularyUtil) {
		File xmlFile = null;
		try {
			xmlFile = File.createTempFile("geXML", ".temp");
			GIMIAPEGI miapeGI = new MiapeGiXMLAdapter(document, controlVocabularyUtil).adapt();
			Marshaller marshaller = jc.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));
			try {
				marshaller.setProperty("com.sun.xml.bind.indentString", "\t");
			} catch (Exception e) {
				marshaller.setProperty("com.sun.xml.internal.bind.indentString", "\t");
			}
			marshaller.marshal(miapeGI, xmlFile);

		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		final MIAPEGIXmlFile miapegiXmlFile = new MIAPEGIXmlFile(xmlFile);
		miapegiXmlFile.setCvUtil(controlVocabularyUtil);
		return miapegiXmlFile;
	}

	@Override
	public MiapeXmlFile<MiapeGIDocument> toXml(MiapeGIDocument document,
			ControlVocabularyManager cvManager) {
		if (cvManager == null)
			throw new IllegalMiapeArgumentException("ControlVocabularyManager is not set");
		return getFactory().create(document, cvManager);

	}
}